package com.euc.springbootframework.util;

import org.springframework.beans.BeanUtils;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BeanUtil {
    /**
     * 返回一个简单对象：只有某几个属性有值， 其余属性都为null
     * 举个例子，比如要返回包含三个属性的vessel，
     * 用法：
     *      String[] leftProperties = {"id", "vesselName", "vesselCode"};
     *      Vessel vessel = findOne("id");
     *      Vessel newVessel = BeanUtil.getSimpleObject(vessel, leftProperties);
     * note: 如果类属性的set方法不是public，那么返回的值就会为null
     * @param originalObject 包含所有属性的对象
     * @param leftProperties 返回的新对象中只保留哪些有值的属性
     * @return the new instance
     */

    public static <T> T getSimpleObject(T originalObject, String[] leftProperties) {
        Class<?> objectClass = originalObject.getClass();
        Object simpleObject = BeanUtils.instantiate(objectClass);
        String[] ignoreProperties = getIgnoreProperties(objectClass, Arrays.asList(leftProperties));
        BeanUtils.copyProperties(originalObject, simpleObject, ignoreProperties);
        return (T) simpleObject;
    }

    private static List<String> getBeanPropertyNames(Class specifiedClass) {
        List<String> properties = new ArrayList<>();
        PropertyDescriptor[] propertyDescriptors = BeanUtils.getPropertyDescriptors(specifiedClass);
        for(PropertyDescriptor p: propertyDescriptors) {
            properties.add(p.getName());
        }
        return properties;
    }

    public static String[] getIgnoreProperties(Class className, List<String> leftProperties){
        List<String> allProperties = getBeanPropertyNames(className);
        return allProperties.stream().filter(tmpProperty -> !leftProperties.contains(tmpProperty)).toArray(String[]::new);
    }

    public static String[] getIgnoreProperties(Class className, String... leftProperties){
        List<String> allProperties = getBeanPropertyNames(className);
        List<String> leftPropertiesList = Arrays.asList(leftProperties);
        return allProperties.stream().filter(tmpProperty -> !leftPropertiesList.contains(tmpProperty)).toArray(String[]::new);
    }
}
